/******************************************************************************* 
 *  Copyright 2008 Amazon Technologies, Inc.
 *  Licensed under the Apache License, Version 2.0 (the "License"); 
 *  
 *  You may not use this file except in compliance with the License. 
 *  You may obtain a copy of the License at: http://aws.amazon.com/apache2.0
 *  This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 *  CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 *  specific language governing permissions and limitations under the License.
 * ***************************************************************************** 
 *    __  _    _  ___ 
 *   (  )( \/\/ )/ __)
 *   /__\ \    / \__ \
 *  (_)(_) \/\/  (___/
 * 
 *  Amazon EC2 CSharp Library
 *  API Version: 2008-12-01
 *  Generated: Fri Dec 26 23:53:41 PST 2008 
 * 
 */

using System;
using System.Text;
using System.Security.Cryptography;
using System.Globalization;

namespace Amazon.EC2.Util
{

    /// <summary>
    /// This class represents S3 upload policy. Policy string
    /// representaion and signature to be used within EC2 bundling API.
    /// </summary>
    public class S3UploadPolicy
    {
        private String policySignature;
        private String policyString;

        /// <summary>
        /// S3 Upload policy to be used by EC2 API.
        /// </summary>
        /// <param name="awsAccessKeyId">Access Key Id of the signer of the policy</param>
        /// <param name="awsSecretKey">Secret Key of the signer of the policy</param>
        /// <param name="bucketName">Bucket name to upload</param>
        /// <param name="prefix">Prefix for the object keys</param>
        /// <param name="expireInMinutes">Expire, minutes from now</param>
        ///
        public S3UploadPolicy(String awsAccessKeyId,
                String awsSecretKey,
                String bucketName,
                String prefix,
                int expireInMinutes)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("{")
                    .Append("\"expiration\": \"")
                    .Append(GetFormattedTimestamp(expireInMinutes))
                    .Append("\",")
                    .Append("\"conditions\": [")
                    .Append("{\"bucket\": \"")
                    .Append(bucketName)
                    .Append("\"},")
                    .Append("{\"acl\": \"")
                    .Append("ec2-bundle-read")
                    .Append("\"},")
                    .Append("[\"starts-with\", \"$key\", \"")
                    .Append(prefix)
                    .Append("\"]")
                    .Append("]}");
            Encoding encoding = new UTF8Encoding();
            this.policyString = Convert.ToBase64String(encoding.GetBytes(builder.ToString().ToCharArray()));
            this.policySignature = SignPolicy(awsSecretKey, policyString);
        }

        /// <summary>
        /// Base64 representation of the serialized policy.
        /// Use policy generated by this method
        /// for passing to EC2 bunding calls.
        /// </summary>
        /// <returns>Base64 policy</returns>
        public String PolicyString
        {
            get
            {
                return this.policyString;
            }
        }

        /// <summary>
        /// Policy signature in base64 format
        /// Use signature generated by this method
        /// for passing to EC2 bunding calls along with policy.
        /// </summary>
        /// <returns>Base64 signature</returns>
        public String PolicySignature
        {
            get
            {
                return this.policySignature;
            }
        }

        private String SignPolicy(String awsSecretKey, String base64EncodedPolicy)
        {
            Encoding encoding = new UTF8Encoding();
            HMACSHA1 signature = new HMACSHA1(encoding.GetBytes(awsSecretKey));
            return Convert.ToBase64String(signature.ComputeHash(
                encoding.GetBytes(base64EncodedPolicy.ToCharArray())));
        }


        private String GetFormattedTimestamp(int minutesFromNow)
        {
            DateTime dateTime = DateTime.Now.AddMinutes(minutesFromNow);
            return new DateTime(dateTime.Year,
                                dateTime.Month,
                                dateTime.Day,
                                dateTime.Hour,
                                dateTime.Minute,
                                dateTime.Second,
                                dateTime.Millisecond,
                                DateTimeKind.Local)
                               .ToUniversalTime()
                               .ToString("yyyy-MM-dd\\THH:mm:ss.fff\\Z",
                                CultureInfo.InvariantCulture);
        }

    }
}